package com.hy.lightning.commons.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;


public class HttpClient {
	
	public static String sendGet(String url) {
		return sendGet(url, null, 3);
	}
	
	public static String sendGet(String url, List<NameValuePair> params, Header ...headers) {
		return sendGet(url, params, 3, headers);
	}
	
	public static String sendGet(String url, List<NameValuePair> params, int retryCount, Header ...headers) {
		if(retryCount == 0) return null;
		if(params != null && params.size() > 0) {
			String paramMap;
			try {
				paramMap = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
				url += "?"+paramMap;
			} catch (ParseException | IOException e) {
				e.printStackTrace();
			}
		}
		CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet get = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom()    
                .setConnectTimeout(5000).setConnectionRequestTimeout(1000)    
                .setSocketTimeout(5000).build();
        get.setConfig(requestConfig);
        if(headers.length != 0) get.setHeaders(headers);
        HttpResponse response;
		try {
			response = httpClient.execute(get);
			HttpEntity entity = response.getEntity();
	        byte[] bs = null;
	        if(entity != null) {
	        	InputStream in = entity.getContent();
	        	bs = IOUtils.toByteArray(in);
	        	in.close();
	        }
	        return new String(bs, "UTF-8");
		} catch (IOException e) {
			e.printStackTrace();
			if(e instanceof org.apache.http.conn.ConnectTimeoutException) {
				retryCount = retryCount - 1 ;
				return sendGet(url, params, retryCount, headers);
			}
		} finally {
			try {
				httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	public static byte[] sendPost_JSON(String url, String body) {
	    return sendPost_JSON(url, body, "UTF-8");
	}
	
	public static byte[] sendPost_JSON(String url, Map<String,Object> body, String charset) throws JsonGenerationException, JsonMappingException, IOException {
		return sendPost_JSON(url, JSON.toString(body), charset);
	}
	
	public static byte[] sendPost_JSON(String url, String body, String charset) {
		return sendPost_JSON(url, body, charset, 1);
	}
	
	public static byte[] sendPost_JSON(String url, String body, String charset, int retryCount, Header ...headers) {
		HttpPost post = new HttpPost(url);
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom()    
                .setConnectTimeout(5000).setConnectionRequestTimeout(1000)    
                .setSocketTimeout(5000).build();
		post.setConfig(requestConfig);
		if(headers.length != 0) post.setHeaders(headers);
		post.addHeader("Content-Type", "application/json");
		HttpEntity entity = new StringEntity(body, charset);
		post.setEntity(entity);
		CloseableHttpResponse response;
		InputStream in = null;
		try {
			response = httpClient.execute(post);
			in =  response.getEntity().getContent();
			byte[] bytes = IOUtils.toByteArray(in);
			return bytes;
		} catch (IOException e) {
			e.printStackTrace();
			if(e instanceof org.apache.http.conn.ConnectTimeoutException) {
				retryCount = retryCount - 1 ;
				return sendPost_JSON(url, body, charset, retryCount, headers);
			}
		} finally {
			try {
				if(httpClient != null) httpClient.close();
				if(in != null)in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
		
	}
	
	public static String sendPost_FormData(String url, byte[] bytes, String name, String fileName) {
		HttpPost post = new HttpPost(url);
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom()    
                .setConnectTimeout(5000).setConnectionRequestTimeout(1000)    
                .setSocketTimeout(5000).build();
		post.setConfig(requestConfig);
		String boundary = "----WebKitFormBoundaryFBppogBVJ3KXyqhd";
		post.addHeader("Content-Type", "multipart/form-data; boundary="+boundary+"");
		String contentDisposition = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", name, fileName);
		byte[] bs = byteMerger(("--"+boundary).getBytes(),
				"\r\n".getBytes(),
				contentDisposition.getBytes(), 
				"\r\n".getBytes(),
				"Content-Type: application/octet-stream".getBytes(),
				"\r\n".getBytes(),
				"\r\n".getBytes(),
				bytes,
				"\r\n".getBytes(),
				("--"+boundary+"--").getBytes(),
				"\r\n".getBytes());
		HttpEntity entity = new ByteArrayEntity(bs);
		post.setEntity(entity);
		CloseableHttpResponse response;
		InputStream in = null;
		try {
			response = httpClient.execute(post);
			in =  response.getEntity().getContent();
			String r = IOUtils.toString(in, "UTF-8");
			return r;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(in != null)
					in.close();
				if(httpClient != null)
					httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	private static byte[] byteMerger(byte[] ...bytess) {
		int len = 0;
		for(byte[] bytes: bytess) len += bytes.length;
		byte[] allByte = new byte[len];
		int lastLen = 0;
		for(int i =0; i < bytess.length; i++) {
			byte[] bytes = bytess[i];
			System.arraycopy(bytes, 0, allByte, lastLen, bytes.length);
			lastLen += bytes.length;
		}
		return allByte;
	} 
	
	public static void main(String[] args) throws IOException {
		String rel = sendGet("https://google.com", null, 3);
		System.out.println(rel);
	}
}
